//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include "gcondition.h"
#include <aura.h>

CGhostCondition::~CGhostCondition()
{
    if (NULL != m_hCondition) {
        AuraCondition_Destroy(m_hCondition);
        m_hCondition = NULL;
    }
    if (NULL != m_hMutex) {
        AuraMutex_Destroy(m_hMutex);
        m_hMutex = NULL;
    }
}

ECode CGhostCondition::Initialize()
{
    ECode ec = NOERROR;

    ec = AuraMutex_Create(AURA_NULL, AURA_FALSE, &m_hMutex);
    if (FAILED(ec)) {
        goto ErrorExit;
    }
    ec = AuraCondition_Create(&m_hCondition);
    if (FAILED(ec)) {
        goto ErrorExit;
    }
    return ec;

ErrorExit:
    if (NULL != m_hMutex) {
        AuraMutex_Destroy(m_hMutex);
        m_hMutex = NULL;
    }
    return ec;
}

UInt32 CGhostCondition::AddRef(void)
{
    Int32 nRefs = m_nRefs.Increment();

    return (UInt32)nRefs;
}

UInt32 CGhostCondition::Release(void)
{
    Int32 nRefs = m_nRefs.Decrement();
    if (0 == nRefs) {
        GhostFactory factory(this->GetOid());
        Ghost::S_DeleteGhost(&factory, this);
        delete this;
    }

    return (UInt32)nRefs;
}

ECode CGhostCondition::Wait(
        /* [in] */ Millisecond32 msTimeOut,
        /* [out] */ WaitResult * pResult)
{
    ECode ec = NOERROR;

    assert((msTimeOut > 0) || (INFINITE == msTimeOut));
    assert(NULL != pResult);

    ec = (ECode)AuraMutex_Lock(m_hMutex, (Aura_Millisecond32)msTimeOut, (Aura_WaitResult*)pResult);
    if (FAILED(ec)) {
        return ec;
    }
    ec = (ECode)AuraCondition_Wait(m_hCondition, m_hMutex, (Aura_Millisecond32)msTimeOut, (Aura_WaitResult *)pResult);
    if (FAILED(ec)) {
    }
    AuraMutex_Unlock(m_hMutex);

    return ec;
}

ECode CGhostCondition::Pulse()
{
    return (ECode)AuraCondition_Pulse(m_hCondition);
}

ECode CGhostCondition::PulseAll()
{
    return (ECode)AuraCondition_PulseAll(m_hCondition);
}

ECode CGhostConditionFactory::CreateGhost(
                /* [out] */ Ghost ** ppGhost,
                /* [out] */ Boolean * pbExisted)
{
    CGhostCondition * pGhost = NULL;
    ECode ec = NOERROR;

    assert(NULL != ppGhost);
    assert(NULL == pbExisted);

    pGhost = new CGhostCondition();
    if (NULL == pGhost) {
        ec = E_OUT_OF_MEMORY;
        goto ErrorExit;
    }
    ec = pGhost->Initialize();
    if (FAILED(ec)) {
        goto ErrorExit;
    }
    pGhost->AddRef();
    *ppGhost = pGhost;

    return ec;

ErrorExit:
    if (NULL != pGhost) {
        delete pGhost;
    }
    return ec;
}

